
//Author Hannes Hassler, Copyleft Feb. 2012

/*
  This code allows for permanent voltage and current measurements, logging the
  values to Serial Monitor. The date/time-stamp for logging 
  are provided from an external chip (DS1307)
  You can also safely omit the DS1307 breakout chip and its associated cuircuitry, if
  you do not need time and date. Measurement of voltage and current will still work.
  
  In this project there are sensors from voltage, current and temperature included.
  It is easily adapted to contain (and log) more and different sensors.  


  I got the VA-measurement circuit from 
  http://rexpirando.blogspot.com/2011/03/arduino-volt-ammeter-part-1-breadboard.html
  which itself referred further to
  http://electronics-diy.com/70v_pic_voltmeter_amperemeter.php


  Voltage ist calculated with formula U = A_0*(5/1023)*(1+R_100/R_10)
  A_0 denotes the input measured @ analog input 0
  R_100 the upper resistor, R_10 the lower resistor in the voltage measurement part
  The (1+R_100/R_10) coefficient is derived from Kirchhoff's voltage law, 
  (5/1023) refers to Arduino voltage range(5V) and input resolution(maximum 1023)

  R_10 need not to be exactly 10 Kilo Ohm, you may choose different values to measure different
  voltage ranges. (Keep however the R_100 resistance at its value of about 100 Kilo Ohm)
  The maximum voltage for e.g. R_10=5K Ohm and R_100=100K Ohm
  would be 1023*(5/1023)*(1+R_100/R_10)=5*(1+20)=105 Volt.

  You may also exchange the R_0.47 resistor for a bigger one (meaning one with more electrical resistance)
  to measure smaller currents. More electrical resistance means the resistor can be less powerful.
  The physical size a 0.47 Ohm shunt resistor is typically much larger than a regular resistor due to
  its power of 5 to 10 Watt. See the picture of a shunt resistor the bottom of this page
  http://electronics-diy.com/70v_pic_voltmeter_amperemeter.php
  and also the measurement circuit.
  The current measured is I_m = A1*(5/1023)/R_0.47 
  The maximum current fitting into the the 0V to 5V range is (for 0.47 Ohm resistor) 5*0.47=2.35A;
  
  Note that the "real current" I_no_amm (i.e. without attached ammeter) is slightly higher than I_m
  This value can be calculated with the additional help 
  of previously received value U(c. above) using formula I_no_amm=U*I_m/(U-I_m*R_0.47)  
*/



#include "Wire.h"
#include <DS1107H.h>

const int PIN_VOLTAGE = 0; //A0
const int PIN_CURRENT = 1; //A1

const boolean NEWLINE=true;
const boolean NONEWLINE=false;


int VOLTAGE_PINVAL;

unsigned long VOLTAGE_MILLIS;
float VOLTAGE_CALCULATED;

int CURRENT_PINVAL;

unsigned long CURRENT_MILLIS;
float CURRENT_CALCULATED;
float CURRENT_SANS_AMP;
float VERBRAUCHER_WIDERSTAND;





float V100K_RESISTOR = 100.0;
float V10K_RESISTOR  = 10.0;




/*for small currents, like LED with a 330 Ohm resistor use resistor with 
 a value of this magnitude*/
//float I0_47_RESISTOR = 47;

/*for larger currents, you need a shunt resistor of a lower value which
allows for accordingly more Watt. If you use such a resistor remove the 
comments in the following line and comment out the line above, respectively.
*/
float I0_47_RESISTOR = 0.47;

float milli_koeff=1000;

float V_Koeff;
float C_Koeff;
float Ard5VoltRef=5.09;


char ch;

boolean log_permanent=false;

DS1107H clock;

//to set the timer chip
//edit the following values and upload with s
/////
byte second=0;
byte minute=56;
byte hour=22;
byte dayOfWeek=6;
byte dayOfMonth=24;
byte month=9;
byte year=11;
/////


void setup() {
  
  pinMode(PIN_VOLTAGE, INPUT);
  pinMode(PIN_CURRENT, INPUT);
  
  V_Koeff=Ard5VoltRef*(1+V100K_RESISTOR/V10K_RESISTOR)/1023.0;
  C_Koeff=Ard5VoltRef*milli_koeff/(I0_47_RESISTOR*1023); //additionally multiplied with 1000 to show milliAmps
	
  Serial.begin(9600); 
 
}

void loop() {
  
 if (log_permanent) {
        readVoltage();
        readCurrent();
        calcVerbraucherWiderstand();
        float mWatt=VOLTAGE_CALCULATED*CURRENT_CALCULATED;
        if (VOLTAGE_CALCULATED>0.01 && CURRENT_CALCULATED>0.01) {
          show("V",VOLTAGE_CALCULATED,NONEWLINE);
          show(";mA",CURRENT_CALCULATED,NONEWLINE);
          show(";R_v",VERBRAUCHER_WIDERSTAND,NONEWLINE);          
          show(";mW",mWatt,NONEWLINE);
          clock.getDate();
          printTimeLog(clock);
        }
        delay(500);       
  }
 
 String timeLogTemp;
 static int v = 0; 

 if (Serial.available()) { 
      ch = Serial.read();              
      
     switch(ch) {
     case '0'...'9':
        v = v * 10 + ch - '0';
        break;
      case 'e':
        readVoltage();
        readCurrent();
        calcVerbraucherWiderstand();
        show("V",VOLTAGE_CALCULATED,NONEWLINE);
        show(";mA",CURRENT_CALCULATED,NONEWLINE);
        show(";R_v",VERBRAUCHER_WIDERSTAND,NONEWLINE);
        clock.getDate();
        printTimeLog(clock);        
        break;
      case 'E':
        log_permanent=true;  
        Serial.println("log permanent on\n");     
        break;        
      case 'F':
        log_permanent=false;
        Serial.println("log permanent OFF\n");
        break;
      case 'f':
       show("set minute:", v, NEWLINE);
       minute=v;
       v=0;break;
      case 'v':
        readVoltage();
        show("voltage(V)",VOLTAGE_CALCULATED,NEWLINE);             
        break; 
      case 'V':
        readVoltage();        
        show("voltagePIN Val",VOLTAGE_PINVAL,NEWLINE);        
        break;
      case 'c':
        readCurrent();
        show("current(mA)",CURRENT_CALCULATED,NEWLINE);             
        break;
      case 'C':
        readCurrent();
        show("currentPIN Val",CURRENT_PINVAL,NEWLINE);             
        break; 
      case 'k':        
        show("V_Koeff",V_Koeff,NEWLINE);             
        break;
      case 'l':        
        show("C_Koeff",C_Koeff,NEWLINE);             
        break; 
       case 'm':        
        readVoltage();
        readCurrent();
        calcRealCurrent();
        show("real current",CURRENT_SANS_AMP,NEWLINE);             
        break;  
      case 's':
         clock.setDate(second,minute,hour,dayOfWeek,dayOfMonth,month,year);
         Serial.println("upload time to timer Chip");
         clock.getDate();
         showTime(clock);
         break;
      case 'z':        
        clock.getDate(); 
        showTime(clock);
      break;  
        
    }
  }  
 
 
}


void show(char nameStr[], double val, boolean newline) {
  Serial.print(nameStr);  
  Serial.print("=");
  if (newline)
       Serial.println(val);
  else Serial.print(val);
}

void printTimeLog(DS1107H timerChip) { 
  Serial.print(";time=");
  Serial.print(timerChip.hour, DEC);
  Serial.print(":");
  Serial.print(timerChip.minute, DEC);
  Serial.print(":");
  Serial.print(timerChip.second, DEC);
  
  Serial.print(";day=");
  Serial.print(timerChip.dayOfMonth, DEC);
  Serial.print(";monat=");
  Serial.print(timerChip.month, DEC);
  Serial.print("\n");
}

void showTime(DS1107H timerChip) {
  Serial.print("UT ");
  Serial.print(timerChip.hour, DEC);
  Serial.print(":");
  Serial.print(timerChip.minute, DEC);
  Serial.print(":");
  Serial.print(timerChip.second, DEC);
  Serial.print("  ");
  Serial.print(timerChip.month, DEC);
  Serial.print("/");
  Serial.print(timerChip.dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(timerChip.year, DEC);
  Serial.print("  Day_of_week:");
  Serial.println(timerChip.dayOfWeek, DEC);  
}


void readVoltage()
{
  VOLTAGE_PINVAL = analogRead(PIN_VOLTAGE);       
  VOLTAGE_CALCULATED=VOLTAGE_PINVAL*V_Koeff; 
}

void readCurrent()
{
  CURRENT_PINVAL = analogRead(PIN_CURRENT);
  CURRENT_CALCULATED= CURRENT_PINVAL*C_Koeff;  
}

void calcVerbraucherWiderstand() {
  float GESAMT_R=milli_koeff*VOLTAGE_CALCULATED/CURRENT_CALCULATED;
  VERBRAUCHER_WIDERSTAND=GESAMT_R-I0_47_RESISTOR;
}

void calcRealCurrent() {
   CURRENT_SANS_AMP=VOLTAGE_CALCULATED*CURRENT_CALCULATED/(VOLTAGE_CALCULATED-(CURRENT_CALCULATED*I0_47_RESISTOR/milli_koeff));   
}



